#include "stm32f10x.h"

#include "drv_uart.h"
#include "usartCfgInfo.h"
#define UART_RX_BUFFER_SIZE 1024  // 接收缓冲区大小

uint8_t Serial_RxData;		//定义串口接收的数据变量

/* 环形缓冲区结构体 - 内部私有 */
typedef struct {
    char buffer[UART_RX_BUFFER_SIZE];   // 数据缓冲区
    uint16_t head;                       // 读指针
    uint16_t tail;                       // 写指针
    uint16_t count;                      // 当前数据量
} RingBuffer;

RingBuffer rxBuffer[USART_MAX_NUM];

// 初始化环形缓冲区
static void ringBufferInit(RingBuffer *buffer) 
{
    buffer->head = 0;
    buffer->tail = 0;
    buffer->count = 0;
}

static uint16_t ringBufferAvailable(RingBuffer* buffer) 
{
    return buffer->count;
}

static uint16_t ringBufferSpace(RingBuffer* buffer) 
{
    return UART_RX_BUFFER_SIZE - buffer->count;
}

// 向环形缓冲区添加一个字节
static uint8_t ringBufferPut(RingBuffer* buffer, char data) {
    if (buffer->count >= UART_RX_BUFFER_SIZE) {
        return 0;  // 缓冲区已满
    }
    
    buffer->buffer[buffer->tail] = data;
    buffer->tail = (buffer->tail + 1) % UART_RX_BUFFER_SIZE;
    buffer->count++;
    return 1;
}

//从环形缓冲区取一个字节
static uint8_t ringBufferGet(RingBuffer* buffer, char* data) {
    if (buffer->count == 0) {
        return 0;  // 缓冲区为空
    }
    
    *data = buffer->buffer[buffer->head];
    buffer->head = (buffer->head + 1) % UART_RX_BUFFER_SIZE;
    buffer->count--;
    return 1;
}


//初始化串口
int uartInit(UART_Handle handle, int baudrate)
{
    if(handle >= USART_MAX_NUM)return -1;
    
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    USART_Config_t* pUsartCfgInfo = &usartCfg[handle];
    
    if(pUsartCfgInfo->instance == USART1){
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//开启USART1的时钟
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
    }else if(pUsartCfgInfo->instance == USART2){
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	//开启USART2的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
        
    }else{
        return -1;
    }
    ringBufferInit(&rxBuffer[handle]);
    
    /*GPIO初始化*/
    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = pUsartCfgInfo->rxPin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA9引脚初始化为复用推挽输出
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = pUsartCfgInfo->txPin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA10引脚初始化为上拉输入
    
    /*USART初始化*/
    USART_InitTypeDef USART_InitStructure;					//定义结构体变量
	USART_InitStructure.USART_BaudRate = pUsartCfgInfo->baudRate;				//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制，不需要
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;	//模式，发送模式和接收模式均选择
	USART_InitStructure.USART_Parity = USART_Parity_No;		//奇偶校验，不需要
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//停止位，选择1位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//字长，选择8位
	USART_Init(pUsartCfgInfo->instance, &USART_InitStructure);				//将结构体变量交给USART_Init，配置USART1
	

	/*中断输出配置*/
	USART_ITConfig(pUsartCfgInfo->instance, USART_IT_RXNE, ENABLE);	


	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;					//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = pUsartCfgInfo->irq;		//选择配置NVIC的USART线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = pUsartCfgInfo->PreemptPriority;		//指定NVIC线路的抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = pUsartCfgInfo->SubPriority;		//指定NVIC线路的响应优先级
	NVIC_Init(&NVIC_InitStructure);							//将结构体变量交给NVIC_Init，配置NVIC外设
	
	/*USART使能*/
	USART_Cmd(pUsartCfgInfo->instance, ENABLE);								//使能USART1，串口开始运行

    return 0;
}

//关闭串口
int uartDeinit(UART_Handle handle)
{
    USART_Config_t* pUsartCfgInfo = &usartCfg[handle];
    
    if(pUsartCfgInfo->instance == USART1){
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, DISABLE);	//关闭USART2的时钟
    }else if(pUsartCfgInfo->instance == USART2){
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
    }else{
        return -1;
    }
    USART_ITConfig(pUsartCfgInfo->instance, USART_IT_RXNE, DISABLE);	

    return 0;
}

//发送数据
int uartSendData(UART_Handle handle, char *data, int len)
{
    USART_Config_t* pUsartCfgInfo = &usartCfg[handle];
	for(int i = 0; i < len ; i++){
        USART_SendData(pUsartCfgInfo->instance, (uint8_t)data[i]);		//将字节数据写入数据寄存器，写入后USART自动生成时序波形
        while (USART_GetFlagStatus(pUsartCfgInfo->instance, USART_FLAG_TXE) == RESET);	//等待发送完成
        /*下次写入数据寄存器会自动清除发送完成标志位，故此循环后，无需清除标志位*/   		
	}
    return 0;
}

//获取接收缓冲区数据长度
int getRecvDataLen(UART_Handle handle)
{
    RingBuffer *pRxBuffer = &rxBuffer[handle];

    return ringBufferAvailable(pRxBuffer);
}

//接收数据
int uartRecvData(UART_Handle handle, char *data, int len)
{
    RingBuffer *pRxBuffer = &rxBuffer[handle];

    uint16_t available = ringBufferAvailable(pRxBuffer);
    uint16_t readCount = (available < len) ? available : len;
    
    for (uint16_t i = 0; i < readCount; i++) {
        if (!ringBufferGet(pRxBuffer, &data[i])) {
            break;
        }
    }
    
    return readCount;
}

/**
  * @brief  UART中断处理函数
  * @param  handle 串口句柄
  * @retval None
  */
void UART_IRQHandler(UART_Handle handle)
{
    USART_Config_t* pUsartCfgInfo = &usartCfg[handle];
    RingBuffer *pRxBuffer = &rxBuffer[handle];   

    if (USART_GetITStatus(pUsartCfgInfo->instance, USART_IT_RXNE) == SET)		//判断是否是USART的接收事件触发的中断
	{
        
		Serial_RxData = USART_ReceiveData(pUsartCfgInfo->instance);	//读取数据寄存器，存放在接收的数据变量
        ringBufferPut(pRxBuffer, Serial_RxData);
		USART_ClearITPendingBit(pUsartCfgInfo->instance, USART_IT_RXNE);			//清除USART1的RXNE标志位
																//读取数据寄存器会自动清除此标志位
																//如果已经读取了数据寄存器，也可以不执行此代码
	}
    
}

/**
  * 函    数：USART1中断函数
  * 参    数：无
  * 返 回 值：无
  * 注意事项：此函数为中断函数，无需调用，中断触发后自动执行
  *           函数名为预留的指定名称，可以从启动文件复制
  *           请确保函数名正确，不能有任何差异，否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
    UART_IRQHandler(0);
	
}

/*重定向printf的输出到USART1*/
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;  

int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);
	USART1->DR=(u8)ch;      
	return ch;
}